//
//  TxMapViewController.swift
//  TencentMap
//
//  Created by 吴非 on 2022/5/18.
//

import UIKit
import QMapKit

class TxMapViewController: UIViewController, QMSSearchDelegate, QMapViewDelegate {
  
    /// 地图
    private lazy var mapView: QMapView = {
        let iView = QMapView(frame: view.bounds)
        iView.delegate = self
        iView.zoomLevel = 17
        iView.showsUserLocation = true
        return iView
    }()
    
    /// 搜索
    private lazy var mapSearcher: QMSSearcher = {
        let iView = QMSSearcher(delegate: self)
        return iView
    }()
    
    /// 列表
    private lazy var bodyTable: UITableView = {
        let iView = UITableView(frame: .zero, style: .plain)
        iView.contentInset.top += 50
        iView.setContentOffset(CGPoint.init(x: 0, y: -50), animated: false)
        iView.delegate = self
        iView.dataSource = self
        iView.isHidden = true
        return iView
    }()
    
    
    /// 搜索控制器
    private lazy var vcSearch: UISearchController = {
        let controller = UISearchController(searchResultsController: nil)
        controller.searchResultsUpdater = self
        controller.obscuresBackgroundDuringPresentation = false
        controller.hidesNavigationBarDuringPresentation = false
        controller.searchBar.delegate = self
        controller.searchBar.placeholder = "请输入地址关键字"
        controller.searchBar.searchBarStyle = .minimal
        controller.searchBar.sizeToFit()
        return controller
    }()
    
    private lazy var barLayer: UIView = {
        let iView  = UIView.init()
        iView.backgroundColor = UIColor.white
        return iView
    }()
    
    private lazy var iconLayer: UIImageView = {
        let iView = UIImageView.init()
        iView.image = bbImage("icon_location")
        return iView
    }()
    
    private lazy var addrLayer: UILabel = {
        let lable = UILabel.init()
        lable.textAlignment = .left
        lable.font = UIFont.systemFont(ofSize: 12)
        lable.textColor = UIColor.black
        lable.numberOfLines = 3
        lable.text = "定位中,请耐心等待..."
        return lable
    }()
    
    private lazy var defineTapper: UIButton = {
        let btn = UIButton.init(type: .custom)
        btn.layer.cornerRadius = 3.0
        btn.titleLabel?.font = UIFont.systemFont(ofSize: 14)
        btn.setTitle("确定", for: .normal)
        btn.backgroundColor = UIColor.blue.withAlphaComponent(0.618)
        btn.setTitleColor(UIColor.white, for: .normal)
        btn.addTarget(self, action: #selector(check(sender:)), for: .touchUpInside)
        btn.setTitleColor(UIColor(white: 0.8, alpha: 0.5), for: .highlighted)
        return btn
    }()
    
    /// 返回按钮样式
    public lazy var gobackButton: UIButton = {
        let iView = UIButton(type: .custom)
        iView.setImage(bbImage("icon_navigation_back"), for: .normal)
        iView.contentHorizontalAlignment = .left
        iView.frame = CGRect(origin: .zero, size: CGSize(width: 48, height: 34))
        iView.addTarget(self, action: #selector(onBack(sender:)), for: .touchUpInside)
        return iView
    }()
    
    // MARK: - 操作数据
    
    // 检索地址列表
    private var poiDataSource: [QMSPoiData] = []
    // 当前中心位置
    private var nowAddrees: TxMapMapper = TxMapMapper()
    // 复用标签
    private let rCellIdentifier = String.init(describing: UITableViewCell.self)
    private let rAnnoIdentifier = String(describing: QPointAnnotation.self)

    /**定位完成*/
    var completionTrigger : TxLocationResponseHandler?

    // 弹出方式
    var isModalityValue: Bool = true
    
    override func viewDidLoad() {
        super.viewDidLoad()
        title = "地图搜索"
        self.navigationController?.navigationBar.isTranslucent = false
        self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: gobackButton)
        self.gobackButton.isHidden = self.isModalityValue
        // Do any additional setup after loading the view.
        initialiUI()
        updateLayer()
    }
    
    private func initialiUI() {
        /// 添加搜索
        self.navigationItem.titleView = self.vcSearch.searchBar
        /// 地图图层
        self.view.addSubview(self.mapView)
        /// 地址列表
        self.view.addSubview(self.bodyTable)
        
        self.view.addSubview(self.barLayer)
        self.barLayer.addSubview(self.iconLayer)
        self.barLayer.addSubview(self.addrLayer)
        self.barLayer.addSubview(self.defineTapper)
    }
    
    private func updateLayer() {
        
        self.mapView.translatesAutoresizingMaskIntoConstraints = false
        self.mapView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        self.mapView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        self.mapView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.mapView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        
        self.bodyTable.translatesAutoresizingMaskIntoConstraints = false
        self.bodyTable.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        self.bodyTable.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        self.bodyTable.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.bodyTable.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
        
        self.barLayer.translatesAutoresizingMaskIntoConstraints = false
        self.barLayer.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
        self.barLayer.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
        self.barLayer.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        self.barLayer.heightAnchor.constraint(equalToConstant: 50).isActive = true
        
        self.defineTapper.translatesAutoresizingMaskIntoConstraints = false
        self.defineTapper.centerYAnchor.constraint(equalTo: self.barLayer.centerYAnchor).isActive = true
        self.defineTapper.rightAnchor.constraint(equalTo: self.barLayer.rightAnchor, constant: -10).isActive = true
        self.defineTapper.widthAnchor.constraint(equalToConstant: 60).isActive = true
        self.defineTapper.heightAnchor.constraint(equalToConstant: 28).isActive = true

        self.iconLayer.translatesAutoresizingMaskIntoConstraints = false
        self.iconLayer.centerYAnchor.constraint(equalTo: self.barLayer.centerYAnchor).isActive = true
        self.iconLayer.leftAnchor.constraint(equalTo: self.barLayer.leftAnchor, constant: 10).isActive = true
        self.iconLayer.widthAnchor.constraint(equalToConstant: 18).isActive = true
        self.iconLayer.heightAnchor.constraint(equalToConstant: 18).isActive = true
        
        self.addrLayer.translatesAutoresizingMaskIntoConstraints = false
        self.addrLayer.centerYAnchor.constraint(equalTo: self.barLayer.centerYAnchor).isActive = true
        self.addrLayer.leftAnchor.constraint(equalTo: self.barLayer.leftAnchor, constant: 30).isActive = true
        self.addrLayer.rightAnchor.constraint(equalTo: self.barLayer.rightAnchor, constant: -70).isActive = true
        self.addrLayer.heightAnchor.constraint(equalToConstant: 18).isActive = true
    }
    
    
    /// 完成
    @objc func check(sender: UIButton) {
        self.completionTrigger?(self.nowAddrees)
        if isModalityValue {
            self.dismiss(animated: true)
        } else {
            self.navigationController?.popViewController(animated: true)
        }
    }
    
    /// 返回
    @objc func onBack(sender: UIButton) {
        if isModalityValue {
            self.dismiss(animated: true)
        } else {
            self.navigationController?.popViewController(animated: true)
        }
    }
    
    
    /*
     // MARK: - Navigation
     
     // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
     // Get the new view controller using segue.destination.
     // Pass the selected object to the new view controller.
     }
     */
    
    // MARK: - QMSSearchDelegate
    
    
    // 坐标搜索
    func search(with reverseGeoCodeSearchOption: QMSReverseGeoCodeSearchOption, didReceive reverseGeoCodeSearchResult: QMSReverseGeoCodeSearchResult) {
        // 记录当前点击位置
        
        self.nowAddrees.address = reverseGeoCodeSearchResult.address ?? ""
        // 安全解析地址
        guard let resp_addr_info = reverseGeoCodeSearchResult.ad_info else { return }
    
        self.nowAddrees.longitude = resp_addr_info.location.longitude
        self.nowAddrees.latitude = resp_addr_info.location.latitude
        self.nowAddrees.location = resp_addr_info.location
        self.nowAddrees.nation = kk_SafetyValue(resp_addr_info.nation)
        self.nowAddrees.province = kk_SafetyValue(resp_addr_info.province)
        self.nowAddrees.city = kk_SafetyValue(resp_addr_info.city)
        self.nowAddrees.district = kk_SafetyValue(resp_addr_info.district)
        self.nowAddrees.street = kk_SafetyValue(reverseGeoCodeSearchResult.address_component.street)
        self.nowAddrees.street_number = kk_SafetyValue(reverseGeoCodeSearchResult.address_component.street_number)
        
        self.addrLayer.text = self.nowAddrees.address
    }
    
    // 关键字搜索
    func search(with poiSearchOption: QMSPoiSearchOption, didReceive poiSearchResult: QMSPoiSearchResult) {
        poiDataSource = poiSearchResult.dataArray as? [QMSPoiData] ?? []
        self.bodyTable.reloadData()
    }
    
    // MARK: - QMapViewDelegate
    
    /**
     * @brief  点击地图空白处会调用此接口.
     * @param mapView 地图View
     * @param coordinate 坐标
     */
    func mapView(_ mapView: QMapView!, didTapAt coordinate: CLLocationCoordinate2D) {
        
        self.askByAddrInfor(coordinate: coordinate)
        
        self.addAnnotation(coordinate: coordinate)
    }
    
    /**
     * @brief  点击地图poi图标处会调用此接口.
     * @param mapView 地图View
     * @param poi poi数据
     */
    func mapView(_ mapView: QMapView!, didTapPoi poi: QPoiInfo!) {
        
        self.askByAddrInfor(coordinate: poi.coordinate)
        
        self.addAnnotation(coordinate: poi.coordinate)
    }
    
    /**
     * @brief 根据anntation生成对应的View
     * @param mapView 地图View
     * @param annotation 指定的标注
     * @return 生成的标注View
     */
    func mapView(_ mapView: QMapView!, viewFor annotation: QAnnotation!) -> QAnnotationView! {
        
        if let pointAnnotation = annotation as? QPointAnnotation {
            let annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: rAnnoIdentifier) as? QPinAnnotationView ?? QPinAnnotationView(annotation: pointAnnotation, reuseIdentifier: rAnnoIdentifier)
            annotationView?.isDraggable = true
            annotationView?.animatesDrop = true
            return annotationView
        }
        
        return nil;
    }
   
    /**
     * @brief 用户位置更新后，会调用此函数
     * @param mapView 地图View
     * @param userLocation 新的用户位置
     * @param fromHeading 是否为heading 变化触发，如果为location变化触发,则为NO
     */
    func mapView(_ mapView: QMapView!, didUpdate userLocation: QUserLocation!, fromHeading: Bool) {
        
        // 更新中心点位置
        if let coordinate: CLLocationCoordinate2D = userLocation.location?.coordinate as? CLLocationCoordinate2D {
            self.mapView.centerCoordinate = coordinate;
            // 停止继续定位
            mapView.showsUserLocation = false
            // 查询逆地址
            self.askByAddrInfor(coordinate: coordinate)
            // 插入大头针
            self.addAnnotation(coordinate: coordinate)
        }
    }


}

extension TxMapViewController {
    
    // 添加大头针
    private func addAnnotation(coordinate: CLLocationCoordinate2D) {
        // 保持只有一个 & 移除之前的
        self.mapView.removeAnnotations(self.mapView.annotations)
        
        let annotation = QPointAnnotation()
        annotation.coordinate = coordinate
        self.mapView.addAnnotation(annotation)
        self.mapView.setCenter(annotation.coordinate, animated: true)
        self.mapView.selectAnnotation(annotation, animated: true)
    }
    
    // 根据坐标查询名称
    private func askByAddrInfor(coordinate: CLLocationCoordinate2D) {
        let revGeoOption = QMSReverseGeoCodeSearchOption()
        revGeoOption.setLocationWithCenter(coordinate)
        self.mapSearcher.search(with: revGeoOption)
    }
    
    // 根据名称检索
    private func askByKeyword(strValue: String, cityName: String, centerCoordinate: CLLocationCoordinate2D) {
        let poiSearchOption = QMSPoiSearchOption()
        poiSearchOption.keyword = strValue
        poiSearchOption.setBoundaryByRegionWithCityName(cityName, autoExtend: false, center: centerCoordinate)
        self.mapSearcher.search(with: poiSearchOption)
    }
}

// MARK: - UISearchResultsUpdating & UISearchBarDelegate
extension TxMapViewController : UISearchResultsUpdating, UISearchBarDelegate {
    
    func updateSearchResults(for searchController: UISearchController) {
        
        self.bodyTable.isHidden = !searchController.isActive
        
        guard let kwValue = searchController.searchBar.text, !kwValue.isEmpty else { return }
    
        self.askByKeyword(strValue: kwValue, cityName: self.nowAddrees.city, centerCoordinate: self.nowAddrees.location)
        
        if searchController.isActive && kwValue.isEmpty {
            searchController.searchBar.placeholder = searchController.searchBar.text
        }
    }
}

// MARK: - UITableViewDataSource
extension TxMapViewController : UITableViewDataSource, UITableViewDelegate {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return poiDataSource.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: rCellIdentifier) ?? UITableViewCell(style: .subtitle, reuseIdentifier: rCellIdentifier)
        let tip:QMSPoiData = poiDataSource[indexPath.row]
        cell.textLabel?.text = tip.title
        cell.detailTextLabel?.text = tip.address
        return cell
    }
    
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        let dm = poiDataSource[indexPath.row]
        // 可以直接在地图打点
        self.addAnnotation(coordinate: dm.location)
        
        self.askByAddrInfor(coordinate: dm.location)
        
        self.vcSearch.isActive = false
    }
    
}

// 安全取数值
func kk_SafetyValue(_ strValue: String?) -> String {
    print("定位地址信息解析错误 ==> \(String(describing: strValue))")
    return strValue == nil ? "" : (strValue ?? "")
}
